package com.zmn.plat.business.impl.service.item.config;

import java.util.*;

import javax.annotation.Resource;

import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.service.item.config.ServiceItemTimeConfigBService;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.model.entity.service.item.ServiceItem;
import com.zmn.plat.model.entity.service.item.config.ServiceItemTimeConfig;
import com.zmn.plat.model.vo.service.item.config.ServiceItemTimeConfigVO;
import com.zmn.plat.services.interfaces.service.item.ServiceItemService;
import com.zmn.plat.services.interfaces.service.item.config.ServiceItemTimeConfigService;

import lombok.extern.log4j.Log4j2;

/**
 * @author tanbiao
 * @description
 * @modifier
 * @since 2020/7/30 15:38
 **/
@Service
@Log4j2
public class ServiceItemTimeConfigBServiceImpl implements ServiceItemTimeConfigBService {
    @Resource
    private ServiceItemTimeConfigService faultItemTimeConfigService;
    @Resource
    private ServiceItemService faultItemService;

    private static String TIME_STYLE = "HH:mm:ss";
    private static String TIME_SPLITER = ":";
    private static String DATE_SPLITER = "-";
    private static String DATE_TIME_SPLITER = " - ";

    @Override
    public List<ServiceItemTimeConfigVO> listByItemId(Integer itemId) {
        if (!NumberUtil.isPositiveInteger(itemId)) {
            log.error("listByItemId itemId can't be null");
            return Collections.emptyList();
        }

        List<ServiceItemTimeConfig> list = faultItemTimeConfigService.listByItemId(itemId);
        if (!CollectionUtils.isEmpty(list)) {
            List<ServiceItemTimeConfigVO> retList = new ArrayList<>(list.size());
            Map<String, ServiceItemTimeConfigVO> timeVoMap = new LinkedHashMap<>(list.size());
            BeanCopier copier = BeanCopier.create(ServiceItemTimeConfig.class, ServiceItemTimeConfigVO.class, false);
            for (ServiceItemTimeConfig config : list) {
                // 将日期格式转换为显示的样式
                String startDateStr = DateUtil.toString(config.getStartDate(), DateUtil.FORMAT_DATE);
                String endDateStr = DateUtil.toString(config.getEndDate(), DateUtil.FORMAT_DATE);
                String startTime = DateUtil.toString(config.getStartTime(), TIME_STYLE);
                String endTime = DateUtil.toString(config.getEndTime(), TIME_STYLE);
                String dateTimeStr = startDateStr + DATE_TIME_SPLITER + endDateStr;
                String timeStr = startTime + DATE_TIME_SPLITER + endTime;
                ServiceItemTimeConfigVO vo = timeVoMap.get(dateTimeStr);
                if (vo == null) {
                    vo = new ServiceItemTimeConfigVO();
                    copier.copy(config, vo, null);
                    List<String> timeList = new ArrayList<>();
                    timeList.add(timeStr);
                    vo.setTimeStrList(timeList);
                    vo.setDateStr(dateTimeStr);
                    timeVoMap.put(dateTimeStr, vo);
                } else {
                    vo.getTimeStrList().add(timeStr);
                }
            }
            retList.addAll(timeVoMap.values());
            return retList;
        }
        // 不存在新增记录的情况下要显示一组空的数据用于展示
        List<ServiceItemTimeConfigVO> retList = new ArrayList<>();
        ServiceItemTimeConfigVO vo = new ServiceItemTimeConfigVO();
        List<String> arrayList = new ArrayList<>(1);
        arrayList.add("");
        vo.setTimeStrList(arrayList);
        retList.add(vo);
        return retList;
    }

    @Override
    public Integer addEdit(List<ServiceItemTimeConfigVO> configList, Integer itemId, String operator) {
        if (CollectionUtils.isEmpty(configList) || !NumberUtil.isPositiveInteger(itemId)) {
            throw new PlatException("参数不能为空,请检查");
        }

        ServiceItem item = faultItemService.findByKey(itemId);
        if (Objects.isNull(item)) {
            throw new PlatException("项目不存在,请检查");
        }

        // 日期是否合法,区间时间段大小，所有时间段是否有重叠
        validateDate(configList);

        // 先删除 再添加
        faultItemTimeConfigService.deleteByItemId(itemId);

        // 整理参数，不同时间段组合为不同的数据，（同一分组日期只有一个，时间段可以多个，每一个时间段一条数据）
        List<ServiceItemTimeConfig> list = new ArrayList<>(configList.size());
        Date now = DateUtil.getNow();
        for (ServiceItemTimeConfigVO vo : configList) {
            String[] dateArray = vo.getDateStr().split(DATE_TIME_SPLITER);
            Date startDate = DateUtil.parse(dateArray[0], DateUtil.FORMAT_DATE);
            Date endDate = DateUtil.parse(dateArray[1], DateUtil.FORMAT_DATE);
            for (String time : vo.getTimeStrList()) {
                String[] timeArray = time.split(DATE_TIME_SPLITER);
                ServiceItemTimeConfig config = new ServiceItemTimeConfig();
                config.setItemId(itemId);
                config.setGroupId(item.getGroupId());
                config.setCategId(item.getCategId());
                config.setTariffId(item.getTariffId());
                config.setStartDate(startDate);
                config.setEndDate(endDate);
                config.setStartTime(DateUtil.parse(timeArray[0], TIME_STYLE));
                config.setEndTime(DateUtil.parse(timeArray[1], TIME_STYLE));
                config.setCreateTime(now);
                config.setUpdateTime(now);
                config.setCreater(operator);
                config.setUpdater(operator);
                list.add(config);
            }
        }
        return faultItemTimeConfigService.insertBatch(list);
    }

    @Override
    public Integer deleteGroupByConfigId(Integer configId) {
        if (!NumberUtil.isPositiveInteger(configId)) {
            log.error("deleteGroupByConfigId configId can't be null");
            throw new PlatException("参数不能为空");
        }

        ServiceItemTimeConfig config = faultItemTimeConfigService.findByKey(configId);
        if (Objects.isNull(config)) {
            throw new PlatException("数据不存在，请刷新重试");
        }
        return faultItemTimeConfigService.deleteByConfig(config);
    }

    private void validateDate(List<ServiceItemTimeConfigVO> configList) {
        // 日期是否重叠，时间段是否重叠
        int listSize = configList.size();
        for (int m = 0; m < listSize; m++) {
            ServiceItemTimeConfigVO oneVo = configList.get(m);
            // 同一分组内的时间段是否有重叠
            List<String> timeStrlist = oneVo.getTimeStrList();
            int length = timeStrlist.size();

            // 时间是否有重叠
            for (int i = 0; i < length; i++) {
                String one = timeStrlist.get(i);
                // 开始时间必须小于结束时间
                String[] time = one.split(DATE_TIME_SPLITER);
                Integer start = Integer.parseInt(time[0].replaceAll(TIME_SPLITER, ""));
                Integer end = Integer.parseInt(time[1].replaceAll(TIME_SPLITER, ""));
                if (end <= start) {
                    throw new PlatException(oneVo.getDateStr() + "中时间段【" + one + "】区间不合法，开始时间必须小于结束时间");
                }
                for (int j = 0; j < length; j++) {
                    if (i == j) {
                        continue;
                    }
                    String two = timeStrlist.get(j);
                    doCheck(oneVo.getDateStr(), one, two, TIME_SPLITER);
                }
            }

            // 日期是否有重叠
            for (int n = 0; n < listSize; n++) {
                if (m == n) {
                    continue;
                }
                ServiceItemTimeConfigVO twoVo = configList.get(n);
                doCheck("", oneVo.getDateStr(), twoVo.getDateStr(), DATE_SPLITER);
            }

        }
    }

    private void doCheck(String groupTime, String timeOne, String timeTwo, String spliter) {
        String[] time = timeOne.split(DATE_TIME_SPLITER);
        Integer start = Integer.parseInt(time[0].replaceAll(spliter, ""));
        Integer end = Integer.parseInt(time[1].replaceAll(spliter, ""));
        String[] timeT = timeTwo.split(DATE_TIME_SPLITER);
        Integer startT = Integer.parseInt(timeT[0].replaceAll(spliter, ""));
        Integer endT = Integer.parseInt(timeT[1].replaceAll(spliter, ""));
        boolean isin = isContains(start, end, startT, endT);
        if (isin) {
            String message = "";
            if (StringUtil.isNotBlank(groupTime)) {
                message = groupTime + "中时间段【" + timeOne + "】和时间段【" + timeTwo + "】有重叠";
            } else {
                message = "日期【" + timeOne + "】和日期【" + timeTwo + "】有重叠";
            }
            throw new PlatException(message);
        }
    }

    private boolean isContains(Integer oneStart, Integer oneEnd, Integer twoStart, Integer twoEnd) {
        if (oneEnd < twoStart) {
            return false;
        }
        if (oneStart <= twoStart && oneEnd >= twoEnd) {
            return true;
        }
        if (oneStart <= twoStart && oneEnd <= twoEnd) {
            return true;
        }
        return false;
    }

}
